From 24c65654221587a65ba2509fcd102fed7ad24f42 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Fri, 18 Mar 2005 00:48:21 +0000 Subject: [PATCH] bitkeeper revision 1.1236.31.7 (423a2555c55pAD5hNwWY6wV2-lsKfg) Fix timer tick before its due problem (again) Split out hypercall code into separate module First step implementation of domain creation via hypercall --- .rootkeys | 1 + xen/arch/ia64/Makefile | 2 +- xen/arch/ia64/domain.c | 488 +++++++++++++++++++++------------ xen/arch/ia64/hypercall.c | 98 +++++++ xen/arch/ia64/process.c | 69 +---- xen/arch/ia64/vcpu.c | 13 +- xen/arch/ia64/xensetup.c | 4 +- xen/include/public/arch-ia64.h | 2 +- 8 files changed, 422 insertions(+), 255 deletions(-) create mode 100644 xen/arch/ia64/hypercall.c diff --git a/.rootkeys b/.rootkeys index 169081eaca..3b4cb63cb3 100644 --- a/.rootkeys +++ b/.rootkeys @@ -895,6 +895,7 @@ 421098b2PHgzf_Gg4R65YRNi_QzMKQ xen/arch/ia64/dom0_ops.c 421098b2O7jsNfzQXA1v3rbAc1QhpA xen/arch/ia64/dom_fw.c 421098b2ZlaBcyiuuPr3WpzaSDwg6Q xen/arch/ia64/domain.c +4239e98a_HX-FCIcXtVqY0BbrDqVug xen/arch/ia64/hypercall.c 421098b3LYAS8xJkQiGP7tiTlyBt0Q xen/arch/ia64/idle0_task.c 421098b3ys5GAr4z6_H1jD33oem82g xen/arch/ia64/irq.c 421098b3Heh72KuoVlND3CH6c0B0aA xen/arch/ia64/lib/Makefile diff --git a/xen/arch/ia64/Makefile b/xen/arch/ia64/Makefile index fb0511ffe2..7627e28367 100644 --- a/xen/arch/ia64/Makefile +++ b/xen/arch/ia64/Makefile @@ -3,7 +3,7 @@ include $(BASEDIR)/Rules.mk # libs-y += arch/ia64/lib/lib.a OBJS = xensetup.o setup.o time.o irq.o ia64_ksyms.o process.o smp.o \ - xenmisc.o pdb-stub.o acpi.o \ + xenmisc.o pdb-stub.o acpi.o hypercall.o \ machvec.o dom0_ops.o domain.o \ idle0_task.o pal.o hpsim.o efi.o efi_stub.o ivt.o mm_contig.o \ mm_bootmem.o sal.o cmdline.o mm_init.o tlb.o page_alloc.o slab.o \ diff --git a/xen/arch/ia64/domain.c b/xen/arch/ia64/domain.c index b070541751..9cf1bd5e66 100644 --- a/xen/arch/ia64/domain.c +++ b/xen/arch/ia64/domain.c @@ -44,9 +44,11 @@ extern kmem_cache_t *domain_struct_cachep; // initialized by arch/ia64/setup.c:find_initrd() unsigned long initrd_start = 0, initrd_end = 0; +#define IS_XEN_ADDRESS(d,a) ((a >= d->xen_vastart) && (a <= d->xen_vaend)) + extern int loadelfimage(char *); extern int readelfimage_base_and_size(char *, unsigned long, - unsigned long *, unsigned long *, unsigned long *); + unsigned long *, unsigned long *, unsigned long *); unsigned long map_domain_page0(struct domain *); extern unsigned long dom_fw_setup(struct domain *, char *, int); @@ -54,63 +56,63 @@ extern unsigned long dom_fw_setup(struct domain *, char *, int); /* this belongs in include/asm, but there doesn't seem to be a suitable place */ void free_perdomain_pt(struct domain *d) { - dummy(); - //free_page((unsigned long)d->mm.perdomain_pt); + dummy(); + //free_page((unsigned long)d->mm.perdomain_pt); } int hlt_counter; void disable_hlt(void) { - hlt_counter++; + hlt_counter++; } void enable_hlt(void) { - hlt_counter--; + hlt_counter--; } static void default_idle(void) { - if ( hlt_counter == 0 ) - { + if ( hlt_counter == 0 ) + { local_irq_disable(); - if ( !softirq_pending(smp_processor_id()) ) - safe_halt(); - //else + if ( !softirq_pending(smp_processor_id()) ) + safe_halt(); + //else local_irq_enable(); - } + } } void continue_cpu_idle_loop(void) { - int cpu = smp_processor_id(); - for ( ; ; ) - { + int cpu = smp_processor_id(); + for ( ; ; ) + { #ifdef IA64 // __IRQ_STAT(cpu, idle_timestamp) = jiffies #else - irq_stat[cpu].idle_timestamp = jiffies; + irq_stat[cpu].idle_timestamp = jiffies; #endif - while ( !softirq_pending(cpu) ) - default_idle(); - do_softirq(); - } + while ( !softirq_pending(cpu) ) + default_idle(); + do_softirq(); + } } void startup_cpu_idle_loop(void) { - /* Just some sanity to ensure that the scheduler is set up okay. */ - ASSERT(current->domain == IDLE_DOMAIN_ID); - domain_unpause_by_systemcontroller(current->domain); - __enter_scheduler(); - - /* - * Declares CPU setup done to the boot processor. - * Therefore memory barrier to ensure state is visible. - */ - smp_mb(); - init_idle(); + /* Just some sanity to ensure that the scheduler is set up okay. */ + ASSERT(current->domain == IDLE_DOMAIN_ID); + domain_unpause_by_systemcontroller(current->domain); + __enter_scheduler(); + + /* + * Declares CPU setup done to the boot processor. + * Therefore memory barrier to ensure state is visible. + */ + smp_mb(); + init_idle(); #if 0 //do we have to ensure the idle task has a shared page so that, for example, //region registers can be loaded from it. Apparently not... @@ -129,7 +131,7 @@ void startup_cpu_idle_loop(void) } #endif - continue_cpu_idle_loop(); + continue_cpu_idle_loop(); } struct domain *arch_alloc_domain_struct(void) @@ -214,9 +216,9 @@ void domain_relinquish_memory(struct domain *d) // heavily leveraged from linux/arch/ia64/kernel/process.c:copy_thread() // and linux/arch/ia64/kernel/process.c:kernel_thread() void new_thread(struct exec_domain *ed, - unsigned long start_pc, - unsigned long start_stack, - unsigned long start_info) + unsigned long start_pc, + unsigned long start_stack, + unsigned long start_info) { struct domain *d = ed->domain; struct switch_stack *sw; @@ -393,24 +395,38 @@ int elf_sanity_check(Elf_Ehdr *ehdr) return (IS_ELF(*ehdr)); } +static void copy_memory(void *dst, void *src, int size) +{ + if (IS_XEN_ADDRESS(dom0,src)) { + memcpy(dst,src,size); + } + else { + if (__copy_from_user(dst,src,size)) + printf("incomplete user copy\n"); + } +} + void loaddomainelfimage(struct domain *d, unsigned long image_start) { - char *elfbase = image_start; - Elf_Ehdr *ehdr = (Elf_Ehdr *)image_start; - Elf_Phdr *phdr; - int h, filesz, memsz, paddr; - unsigned long elfaddr, dom_mpaddr, dom_imva; - struct page *p; + char *elfbase = image_start; + //Elf_Ehdr *ehdr = (Elf_Ehdr *)image_start; + Elf_Ehdr ehdr; + Elf_Phdr phdr; + int h, filesz, memsz, paddr; + unsigned long elfaddr, dom_mpaddr, dom_imva; + struct page *p; - for ( h = 0; h < ehdr->e_phnum; h++ ) { - phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize)); - //if ( !is_loadable_phdr(phdr) ) - if ((phdr->p_type != PT_LOAD)) { - continue; - } - filesz = phdr->p_filesz; memsz = phdr->p_memsz; - elfaddr = elfbase + phdr->p_offset; - dom_mpaddr = phdr->p_paddr; + copy_memory(&ehdr,image_start,sizeof(Elf_Ehdr)); + for ( h = 0; h < ehdr.e_phnum; h++ ) { + copy_memory(&phdr,elfbase + ehdr.e_phoff + (h*ehdr.e_phentsize), + sizeof(Elf_Phdr)); + //if ( !is_loadable_phdr(phdr) ) + if ((phdr.p_type != PT_LOAD)) { + continue; + } + filesz = phdr.p_filesz; memsz = phdr.p_memsz; + elfaddr = elfbase + phdr.p_offset; + dom_mpaddr = phdr.p_paddr; //printf("p_offset: %x, size=%x\n",elfaddr,filesz); #ifdef CONFIG_DOMAIN0_CONTIGUOUS if (d == dom0) { @@ -419,10 +435,10 @@ void loaddomainelfimage(struct domain *d, unsigned long image_start) while(1); } dom_imva = __va(dom_mpaddr + dom0_start); - memcpy(dom_imva,elfaddr,filesz); + copy_memory(dom_imva,elfaddr,filesz); if (memsz > filesz) memset(dom_imva+filesz,0,memsz-filesz); //FIXME: This test for code seems to find a lot more than objdump -x does - if (phdr->p_flags & PF_X) privify_memory(dom_imva,filesz); + if (phdr.p_flags & PF_X) privify_memory(dom_imva,filesz); } else #endif @@ -432,13 +448,13 @@ void loaddomainelfimage(struct domain *d, unsigned long image_start) dom_imva = __va(page_to_phys(p)); if (filesz > 0) { if (filesz >= PAGE_SIZE) - memcpy(dom_imva,elfaddr,PAGE_SIZE); + copy_memory(dom_imva,elfaddr,PAGE_SIZE); else { // copy partial page, zero the rest of page - memcpy(dom_imva,elfaddr,filesz); + copy_memory(dom_imva,elfaddr,filesz); memset(dom_imva+filesz,0,PAGE_SIZE-filesz); } //FIXME: This test for code seems to find a lot more than objdump -x does - if (phdr->p_flags & PF_X) + if (phdr.p_flags & PF_X) privify_memory(dom_imva,PAGE_SIZE); } else if (memsz > 0) // always zero out entire page @@ -446,66 +462,102 @@ void loaddomainelfimage(struct domain *d, unsigned long image_start) memsz -= PAGE_SIZE; filesz -= PAGE_SIZE; elfaddr += PAGE_SIZE; dom_mpaddr += PAGE_SIZE; } - } + } +} + +int +parsedomainelfimage(char *elfbase, unsigned long elfsize, unsigned long *entry) +{ + Elf_Ehdr ehdr; + + copy_memory(&ehdr,elfbase,sizeof(Elf_Ehdr)); + + if ( !elf_sanity_check(&ehdr) ) { + printk("ELF sanity check failed.\n"); + return -EINVAL; + } + + if ( (ehdr.e_phoff + (ehdr.e_phnum * ehdr.e_phentsize)) > elfsize ) + { + printk("ELF program headers extend beyond end of image.\n"); + return -EINVAL; + } + + if ( (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) > elfsize ) + { + printk("ELF section headers extend beyond end of image.\n"); + return -EINVAL; + } + + /* Find the section-header strings table. */ + if ( ehdr.e_shstrndx == SHN_UNDEF ) + { + printk("ELF image has no section-header strings table (shstrtab).\n"); + return -EINVAL; + } + + *entry = ehdr.e_entry; + + return 0; } void alloc_dom0(void) { #ifdef CONFIG_DOMAIN0_CONTIGUOUS - if (platform_is_hp_ski()) { + if (platform_is_hp_ski()) { dom0_size = 128*1024*1024; //FIXME: Should be configurable - } - printf("alloc_dom0: starting (initializing %d MB...)\n",dom0_size/(1024*1024)); - dom0_start = __alloc_bootmem(dom0_size,dom0_align,__pa(MAX_DMA_ADDRESS)); - if (!dom0_start) { + } + printf("alloc_dom0: starting (initializing %d MB...)\n",dom0_size/(1024*1024)); + dom0_start = __alloc_bootmem(dom0_size,dom0_align,__pa(MAX_DMA_ADDRESS)); + if (!dom0_start) { printf("construct_dom0: can't allocate contiguous memory size=%p\n", dom0_size); while(1); - } - printf("alloc_dom0: dom0_start=%p\n",dom0_start); + } + printf("alloc_dom0: dom0_start=%p\n",dom0_start); #else - dom0_start = 0; + dom0_start = 0; #endif } int construct_dom0(struct domain *d, - unsigned long image_start, unsigned long image_len, - unsigned long initrd_start, unsigned long initrd_len, - char *cmdline) -{ - char *dst; - int i, rc; - unsigned long pfn, mfn; - unsigned long nr_pt_pages; - unsigned long count; - //l2_pgentry_t *l2tab, *l2start; - //l1_pgentry_t *l1tab = NULL, *l1start = NULL; - struct pfn_info *page = NULL; - start_info_t *si; - struct exec_domain *ed = d->exec_domain[0]; - - struct domain_setup_info dsi; - unsigned long p_start; - unsigned long pkern_start; - unsigned long pkern_entry; - unsigned long pkern_end; - - extern void physdev_init_dom0(struct domain *); + unsigned long image_start, unsigned long image_len, + unsigned long initrd_start, unsigned long initrd_len, + char *cmdline) +{ + char *dst; + int i, rc; + unsigned long pfn, mfn; + unsigned long nr_pt_pages; + unsigned long count; + //l2_pgentry_t *l2tab, *l2start; + //l1_pgentry_t *l1tab = NULL, *l1start = NULL; + struct pfn_info *page = NULL; + start_info_t *si; + struct exec_domain *ed = d->exec_domain[0]; + + struct domain_setup_info dsi; + unsigned long p_start; + unsigned long pkern_start; + unsigned long pkern_entry; + unsigned long pkern_end; + + extern void physdev_init_dom0(struct domain *); //printf("construct_dom0: starting\n"); - /* Sanity! */ + /* Sanity! */ #ifndef CLONE_DOMAIN0 - if ( d != dom0 ) - BUG(); - if ( test_bit(DF_CONSTRUCTED, &d->d_flags) ) - BUG(); + if ( d != dom0 ) + BUG(); + if ( test_bit(DF_CONSTRUCTED, &d->d_flags) ) + BUG(); #endif - memset(&dsi, 0, sizeof(struct domain_setup_info)); + memset(&dsi, 0, sizeof(struct domain_setup_info)); - printk("*** LOADING DOMAIN 0 ***\n"); + printk("*** LOADING DOMAIN 0 ***\n"); d->max_pages = dom0_size/PAGE_SIZE; image_start = __va(ia64_boot_param->initrd_start); @@ -514,139 +566,211 @@ int construct_dom0(struct domain *d, //printk("First word of image: %lx\n",*(unsigned long *)image_start); //printf("construct_dom0: about to call parseelfimage\n"); - rc = parseelfimage(image_start, image_len, &dsi); - if ( rc != 0 ) - return rc; + rc = parseelfimage(image_start, image_len, &dsi); + if ( rc != 0 ) + return rc; - p_start = dsi.v_start; - pkern_start = dsi.v_kernstart; - pkern_end = dsi.v_kernend; - pkern_entry = dsi.v_kernentry; + p_start = dsi.v_start; + pkern_start = dsi.v_kernstart; + pkern_end = dsi.v_kernend; + pkern_entry = dsi.v_kernentry; //printk("p_start=%lx, pkern_start=%lx, pkern_end=%lx, pkern_entry=%lx\n",p_start,pkern_start,pkern_end,pkern_entry); - if ( (p_start & (PAGE_SIZE-1)) != 0 ) - { - printk("Initial guest OS must load to a page boundary.\n"); - return -EINVAL; - } + if ( (p_start & (PAGE_SIZE-1)) != 0 ) + { + printk("Initial guest OS must load to a page boundary.\n"); + return -EINVAL; + } - printk("METAPHYSICAL MEMORY ARRANGEMENT:\n" - " Kernel image: %lx->%lx\n" - " Entry address: %lx\n" - " Init. ramdisk: (NOT IMPLEMENTED YET)\n", - pkern_start, pkern_end, pkern_entry); + printk("METAPHYSICAL MEMORY ARRANGEMENT:\n" + " Kernel image: %lx->%lx\n" + " Entry address: %lx\n" + " Init. ramdisk: (NOT IMPLEMENTED YET)\n", + pkern_start, pkern_end, pkern_entry); - if ( (pkern_end - pkern_start) > (d->max_pages * PAGE_SIZE) ) - { - printk("Initial guest OS requires too much space\n" - "(%luMB is greater than %luMB limit)\n", - (pkern_end-pkern_start)>>20, (d->max_pages<>20); - return -ENOMEM; - } + if ( (pkern_end - pkern_start) > (d->max_pages * PAGE_SIZE) ) + { + printk("Initial guest OS requires too much space\n" + "(%luMB is greater than %luMB limit)\n", + (pkern_end-pkern_start)>>20, (d->max_pages<>20); + return -ENOMEM; + } - // if high 3 bits of pkern start are non-zero, error + // if high 3 bits of pkern start are non-zero, error - // if pkern end is after end of metaphysical memory, error - // (we should be able to deal with this... later) + // if pkern end is after end of metaphysical memory, error + // (we should be able to deal with this... later) - // + // #if 0 - strcpy(d->name,"Domain0"); + strcpy(d->name,"Domain0"); #endif // prepare domain0 pagetable (maps METAphysical to physical) // following is roughly mm_init() in linux/kernel/fork.c d->arch.mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); if (unlikely(!d->arch.mm)) { - printk("Can't allocate mm_struct for domain0\n"); - return -ENOMEM; + printk("Can't allocate mm_struct for domain0\n"); + return -ENOMEM; } memset(d->arch.mm, 0, sizeof(*d->arch.mm)); d->arch.mm->pgd = pgd_alloc(d->arch.mm); if (unlikely(!d->arch.mm->pgd)) { - printk("Can't allocate pgd for domain0\n"); - return -ENOMEM; + printk("Can't allocate pgd for domain0\n"); + return -ENOMEM; } - /* Mask all upcalls... */ - for ( i = 0; i < MAX_VIRT_CPUS; i++ ) - d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1; + /* Mask all upcalls... */ + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1; - /* Copy the OS image. */ - //(void)loadelfimage(image_start); + /* Copy the OS image. */ + //(void)loadelfimage(image_start); loaddomainelfimage(d,image_start); - /* Copy the initial ramdisk. */ - //if ( initrd_len != 0 ) - // memcpy((void *)vinitrd_start, initrd_start, initrd_len); + /* Copy the initial ramdisk. */ + //if ( initrd_len != 0 ) + // memcpy((void *)vinitrd_start, initrd_start, initrd_len); #if 0 - /* Set up start info area. */ - //si = (start_info_t *)vstartinfo_start; - memset(si, 0, PAGE_SIZE); - si->nr_pages = d->tot_pages; - si->shared_info = virt_to_phys(d->shared_info); - si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN; - //si->pt_base = vpt_start; - //si->nr_pt_frames = nr_pt_pages; - //si->mfn_list = vphysmap_start; - - if ( initrd_len != 0 ) - { - //si->mod_start = vinitrd_start; - si->mod_len = initrd_len; - printk("Initrd len 0x%lx, start at 0x%08lx\n", - si->mod_len, si->mod_start); - } - - dst = si->cmd_line; - if ( cmdline != NULL ) - { - for ( i = 0; i < 255; i++ ) - { - if ( cmdline[i] == '\0' ) - break; - *dst++ = cmdline[i]; - } - } - *dst = '\0'; - - zap_low_mappings(); /* Do the same for the idle page tables. */ + /* Set up start info area. */ + //si = (start_info_t *)vstartinfo_start; + memset(si, 0, PAGE_SIZE); + si->nr_pages = d->tot_pages; + si->shared_info = virt_to_phys(d->shared_info); + si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN; + //si->pt_base = vpt_start; + //si->nr_pt_frames = nr_pt_pages; + //si->mfn_list = vphysmap_start; + + if ( initrd_len != 0 ) + { + //si->mod_start = vinitrd_start; + si->mod_len = initrd_len; + printk("Initrd len 0x%lx, start at 0x%08lx\n", + si->mod_len, si->mod_start); + } + + dst = si->cmd_line; + if ( cmdline != NULL ) + { + for ( i = 0; i < 255; i++ ) + { + if ( cmdline[i] == '\0' ) + break; + *dst++ = cmdline[i]; + } + } + *dst = '\0'; + + zap_low_mappings(); /* Do the same for the idle page tables. */ #endif - - /* Give up the VGA console if DOM0 is configured to grab it. */ + + /* Give up the VGA console if DOM0 is configured to grab it. */ #ifdef IA64 if (cmdline != NULL) #endif - console_endboot(strstr(cmdline, "tty0") != NULL); + console_endboot(strstr(cmdline, "tty0") != NULL); - /* DOM0 gets access to everything. */ + /* DOM0 gets access to everything. */ #ifdef CLONE_DOMAIN0 if (d == dom0) #endif - physdev_init_dom0(d); + physdev_init_dom0(d); - set_bit(DF_CONSTRUCTED, &d->d_flags); + set_bit(DF_CONSTRUCTED, &d->d_flags); - new_thread(ed, pkern_entry, 0, 0); - // FIXME: Hack for keyboard input + new_thread(ed, pkern_entry, 0, 0); + // FIXME: Hack for keyboard input #ifdef CLONE_DOMAIN0 if (d == dom0) #endif - serial_input_init(); - if (d == dom0) { - ed->vcpu_info->arch.delivery_mask[0] = -1L; - ed->vcpu_info->arch.delivery_mask[1] = -1L; - ed->vcpu_info->arch.delivery_mask[2] = -1L; - ed->vcpu_info->arch.delivery_mask[3] = -1L; - } - else __set_bit(0x30,ed->vcpu_info->arch.delivery_mask); - - return 0; + serial_input_init(); + if (d == dom0) { + ed->vcpu_info->arch.delivery_mask[0] = -1L; + ed->vcpu_info->arch.delivery_mask[1] = -1L; + ed->vcpu_info->arch.delivery_mask[2] = -1L; + ed->vcpu_info->arch.delivery_mask[3] = -1L; + } + else __set_bit(0x30,ed->vcpu_info->arch.delivery_mask); + + return 0; +} + +// FIXME: When dom0 can construct domains, this goes away (or is rewritten) +int construct_domN(struct domain *d, + unsigned long image_start, unsigned long image_len, + unsigned long initrd_start, unsigned long initrd_len, + char *cmdline) +{ + int i, rc; + struct exec_domain *ed = d->exec_domain[0]; + unsigned long pkern_entry; + + if ( test_bit(DF_CONSTRUCTED, &d->d_flags) ) BUG(); + + printk("*** LOADING DOMAIN %d ***\n",d->id); + + d->max_pages = dom0_size/PAGE_SIZE; // FIXME: use dom0 size + // FIXME: use domain0 command line + rc = parsedomainelfimage(image_start, image_len, &pkern_entry); + printk("parsedomainelfimage returns %d\n",rc); + if ( rc != 0 ) return rc; + + d->arch.mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL); + if (unlikely(!d->arch.mm)) { + printk("Can't allocate mm_struct for domain %d\n",d->id); + return -ENOMEM; + } + memset(d->arch.mm, 0, sizeof(*d->arch.mm)); + d->arch.mm->pgd = pgd_alloc(d->arch.mm); + if (unlikely(!d->arch.mm->pgd)) { + printk("Can't allocate pgd for domain %d\n",d->id); + return -ENOMEM; + } + + + /* Mask all upcalls... */ + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1; + + /* Copy the OS image. */ + printk("calling loaddomainelfimage\n"); + loaddomainelfimage(d,image_start); + printk("loaddomainelfimage returns\n"); + + set_bit(DF_CONSTRUCTED, &d->d_flags); + + printk("calling new_thread\n"); + new_thread(ed, pkern_entry, 0, 0); + printk("new_thread returns\n"); + __set_bit(0x30,ed->vcpu_info->arch.delivery_mask); + + return 0; +} + +// FIXME: When dom0 can construct domains, this goes away (or is rewritten) +int launch_domainN(unsigned long start, unsigned long len, + unsigned long initrd_start, unsigned long initrd_len, + char *cmdline) +{ + static int next = 100; // FIXME + + struct domain *d = do_createdomain(next,0); + if (!d) { + printf("launch_domainN: couldn't create\n"); + return 1; + } + if (construct_domN(d, start, len, 0, 0, 0)) { + printf("launch_domainN: couldn't construct(id=%d,%lx,%lx)\n", + d->id,start,len); + return 2; + } + domain_unpause_by_systemcontroller(d); } void machine_restart(char * __unused) diff --git a/xen/arch/ia64/hypercall.c b/xen/arch/ia64/hypercall.c new file mode 100644 index 0000000000..d5eb255065 --- /dev/null +++ b/xen/arch/ia64/hypercall.c @@ -0,0 +1,98 @@ +/* + * Hypercall implementations + * + * Copyright (C) 2005 Hewlett-Packard Co. + * Dan Magenheimer (dan.magenheimer@hp.com) + * + */ + +#include +#include + +#include /* FOR EFI_UNIMPLEMENTED */ +#include /* FOR struct ia64_sal_retval */ + +#include +#include + +extern unsigned long translate_domain_mpaddr(unsigned long); +extern struct ia64_sal_retval pal_emulator_static(UINT64); +extern struct ia64_sal_retval sal_emulator(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64); + +void fooefi(void) {} + +void +ia64_hypercall (struct pt_regs *regs) +{ + struct exec_domain *ed = (struct domain *) current; + struct ia64_sal_retval x; + unsigned long *tv, *tc; + + switch (regs->r2) { + case FW_HYPERCALL_PAL_CALL: + //printf("*** PAL hypercall: index=%d\n",regs->r28); + //FIXME: This should call a C routine + x = pal_emulator_static(regs->r28); + regs->r8 = x.status; regs->r9 = x.v0; + regs->r10 = x.v1; regs->r11 = x.v2; + break; + case FW_HYPERCALL_SAL_CALL: + x = sal_emulator(vcpu_get_gr(ed,32),vcpu_get_gr(ed,33), + vcpu_get_gr(ed,34),vcpu_get_gr(ed,35), + vcpu_get_gr(ed,36),vcpu_get_gr(ed,37), + vcpu_get_gr(ed,38),vcpu_get_gr(ed,39)); + regs->r8 = x.status; regs->r9 = x.v0; + regs->r10 = x.v1; regs->r11 = x.v2; + break; + case FW_HYPERCALL_EFI_RESET_SYSTEM: + printf("efi.reset_system called "); + if (current->domain == dom0) { + printf("(by dom0)\n "); + (*efi.reset_system)(EFI_RESET_WARM,0,0,NULL); + } + printf("(not supported for non-0 domain)\n"); + regs->r8 = EFI_UNSUPPORTED; + break; + case FW_HYPERCALL_EFI_GET_TIME: + fooefi(); + tv = vcpu_get_gr(ed,32); + tc = vcpu_get_gr(ed,33); + //printf("efi_get_time(%p,%p) called...",tv,tc); + tv = __va(translate_domain_mpaddr(tv)); + if (tc) tc = __va(translate_domain_mpaddr(tc)); + regs->r8 = (*efi.get_time)(tv,tc); + //printf("and returns %lx\n",regs->r8); + break; + case FW_HYPERCALL_EFI_SET_TIME: + case FW_HYPERCALL_EFI_GET_WAKEUP_TIME: + case FW_HYPERCALL_EFI_SET_WAKEUP_TIME: + // FIXME: need fixes in efi.h from 2.6.9 + case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP: + // FIXME: WARNING!! IF THIS EVER GETS IMPLEMENTED + // SOME OF THE OTHER EFI EMULATIONS WILL CHANGE AS + // POINTER ARGUMENTS WILL BE VIRTUAL!! + case FW_HYPERCALL_EFI_GET_VARIABLE: + // FIXME: need fixes in efi.h from 2.6.9 + case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE: + case FW_HYPERCALL_EFI_SET_VARIABLE: + case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT: + // FIXME: need fixes in efi.h from 2.6.9 + regs->r8 = EFI_UNSUPPORTED; + break; + case 0xffff: // test dummy hypercall + regs->r8 = dump_privop_counts_to_user( + vcpu_get_gr(ed,32), + vcpu_get_gr(ed,33)); + break; + case 0xfffe: // test dummy hypercall + regs->r8 = zero_privop_counts_to_user( + vcpu_get_gr(ed,32), + vcpu_get_gr(ed,33)); + break; + case 0xfffd: // test dummy hypercall + regs->r8 = launch_domainN( + vcpu_get_gr(ed,32), + vcpu_get_gr(ed,33), 0, 0, 0); + break; + } +} diff --git a/xen/arch/ia64/process.c b/xen/arch/ia64/process.c index 622b142405..7e4b7947d1 100644 --- a/xen/arch/ia64/process.c +++ b/xen/arch/ia64/process.c @@ -696,8 +696,6 @@ if (!running_on_sim) { printf("SSC_OPEN, not implemented on hardware. (ignoring vcpu_increment_iip(current); } -void fooefi(void) {} - void ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long iim) { @@ -716,72 +714,7 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, u else do_ssc(vcpu_get_gr(current,36), regs); } else if (iim == d->breakimm) { - struct ia64_sal_retval x; - switch (regs->r2) { - case FW_HYPERCALL_PAL_CALL: - //printf("*** PAL hypercall: index=%d\n",regs->r28); - //FIXME: This should call a C routine - x = pal_emulator_static(regs->r28); - regs->r8 = x.status; regs->r9 = x.v0; - regs->r10 = x.v1; regs->r11 = x.v2; - break; - case FW_HYPERCALL_SAL_CALL: - x = sal_emulator(vcpu_get_gr(ed,32),vcpu_get_gr(ed,33), - vcpu_get_gr(ed,34),vcpu_get_gr(ed,35), - vcpu_get_gr(ed,36),vcpu_get_gr(ed,37), - vcpu_get_gr(ed,38),vcpu_get_gr(ed,39)); - regs->r8 = x.status; regs->r9 = x.v0; - regs->r10 = x.v1; regs->r11 = x.v2; - break; - case FW_HYPERCALL_EFI_RESET_SYSTEM: - printf("efi.reset_system called "); - if (current->domain == dom0) { - printf("(by dom0)\n "); - (*efi.reset_system)(EFI_RESET_WARM,0,0,NULL); - } - printf("(not supported for non-0 domain)\n"); - regs->r8 = EFI_UNSUPPORTED; - break; - case FW_HYPERCALL_EFI_GET_TIME: - { - unsigned long *tv, *tc; - fooefi(); - tv = vcpu_get_gr(ed,32); - tc = vcpu_get_gr(ed,33); - //printf("efi_get_time(%p,%p) called...",tv,tc); - tv = __va(translate_domain_mpaddr(tv)); - if (tc) tc = __va(translate_domain_mpaddr(tc)); - regs->r8 = (*efi.get_time)(tv,tc); - //printf("and returns %lx\n",regs->r8); - } - break; - case FW_HYPERCALL_EFI_SET_TIME: - case FW_HYPERCALL_EFI_GET_WAKEUP_TIME: - case FW_HYPERCALL_EFI_SET_WAKEUP_TIME: - // FIXME: need fixes in efi.h from 2.6.9 - case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP: - // FIXME: WARNING!! IF THIS EVER GETS IMPLEMENTED - // SOME OF THE OTHER EFI EMULATIONS WILL CHANGE AS - // POINTER ARGUMENTS WILL BE VIRTUAL!! - case FW_HYPERCALL_EFI_GET_VARIABLE: - // FIXME: need fixes in efi.h from 2.6.9 - case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE: - case FW_HYPERCALL_EFI_SET_VARIABLE: - case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT: - // FIXME: need fixes in efi.h from 2.6.9 - regs->r8 = EFI_UNSUPPORTED; - break; - case 0xffff: // test dummy hypercall - regs->r8 = dump_privop_counts_to_user( - vcpu_get_gr(ed,32), - vcpu_get_gr(ed,33)); - break; - case 0xfffe: // test dummy hypercall - regs->r8 = zero_privop_counts_to_user( - vcpu_get_gr(ed,32), - vcpu_get_gr(ed,33)); - break; - } + ia64_hypercall(regs); vcpu_increment_iip(current); } else reflect_interruption(ifa,isr,iim,regs,IA64_BREAK_VECTOR); diff --git a/xen/arch/ia64/vcpu.c b/xen/arch/ia64/vcpu.c index 8698167712..15c9e343e0 100644 --- a/xen/arch/ia64/vcpu.c +++ b/xen/arch/ia64/vcpu.c @@ -639,6 +639,10 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval) PSCB(vcpu,irr[i]) &= ~mask; PSCB(vcpu,pending_interruption)--; *pval = vector; + // if delivering a timer interrupt, remember domain_itm + if (vector == (PSCB(vcpu,itv) & 0xff)) { + PSCB(vcpu,domain_itm_last) = PSCB(vcpu,domain_itm); + } return IA64_NO_FAULT; } @@ -978,8 +982,13 @@ void vcpu_pend_timer(VCPU *vcpu) UINT64 itv = PSCB(vcpu,itv) & 0xff; if (vcpu_timer_disabled(vcpu)) return; - if (vcpu_timer_inservice(vcpu)) return; -#if 1 + //if (vcpu_timer_inservice(vcpu)) return; + if (PSCB(vcpu,domain_itm_last) == PSCB(vcpu,domain_itm)) { + // already delivered an interrupt for this so + // don't deliver another + return; + } +#if 0 // attempt to flag "timer tick before its due" source { UINT64 itm = PSCB(vcpu,domain_itm); diff --git a/xen/arch/ia64/xensetup.c b/xen/arch/ia64/xensetup.c index a72b25174d..a2681500da 100644 --- a/xen/arch/ia64/xensetup.c +++ b/xen/arch/ia64/xensetup.c @@ -362,9 +362,11 @@ printk("About to call construct_dom0()\n"); #ifdef CLONE_DOMAIN0 { int i; + dom0_memory_start = __va(ia64_boot_param->initrd_start); + dom0_memory_end = ia64_boot_param->initrd_size; for (i = 0; i < CLONE_DOMAIN0; i++) { printk("CONSTRUCTING DOMAIN0 CLONE #%d\n",i+1); - if ( construct_dom0(clones[i], dom0_memory_start, dom0_memory_end, + if ( construct_domN(clones[i], dom0_memory_start, dom0_memory_end, 0, 0, 0) != 0) diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index 065b65a9c7..ff53be3d85 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -78,7 +78,7 @@ typedef struct { unsigned long dcr; unsigned long itc; unsigned long domain_itm; - unsigned long domain_timer_interval; + unsigned long domain_itm_last; unsigned long xen_itm; unsigned long xen_timer_interval; //} PACKED arch_shared_info_t; -- 2.30.2